#include "ll_uart.h"
#include "ll_gpio.h"
#include "ll_exti.h"

/************************************************************************************************************
Tabel UART-Pin about stm32f407 gpio alternate for UART
┏━━━━━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┓
┃   function    ┃   pin     ┃  pin      ┃   pin     ┃   DMA request                         ┃  AF MODE       ┃ 
┠━━━━━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┨
┃   UART1_RX    ┃   PA10    ┃  PB7      ┃           ┃   Channel4/DMA2_Steam2/DMA2_Steam5    ┃  LL_GPIO_AF7   ┃
┃   UART1_TX    ┃   PA9     ┃  PB6      ┃           ┃   Channel4/DMA2_Steam7                ┃                ┃
┠━━━━━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┨
┃   UART2_RX    ┃   PA3     ┃  PD6      ┃           ┃   Channel4/DMA1_Steam5                ┃  LL_GPIO_AF7   ┃
┃   UART2_TX    ┃   PA2     ┃  PD5      ┃           ┃   Channel4/DMA1_Steam6                ┃                ┃
┠━━━━━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┨
┃   UART3_RX    ┃   PB11    ┃  PC11     ┃   PD9     ┃   Channel4/DMA1_Steam1                ┃  LL_GPIO_AF7   ┃
┃   UART3_TX    ┃   PB10    ┃  PC10     ┃   PD8     ┃   Channel4/DMA1_Steam3                ┃                ┃
┠━━━━━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┨
┃   UART4_RX    ┃   PA1     ┃  PC11     ┃           ┃   Channel4/DMA1_Steam2                ┃  LL_GPIO_AF8   ┃
┃   UART4_TX    ┃   PA0     ┃  PC10     ┃   PC6     ┃   Channel4/DMA1_Steam4                ┃                ┃
┠━━━━━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┨
┃   UART5_RX    ┃   PD2     ┃           ┃           ┃   Channel4/DMA1_Steam0                ┃  LL_GPIO_AF8   ┃
┃   UART5_TX    ┃   PC12    ┃           ┃           ┃   Channel4/DMA1_Steam7                ┃                ┃
┠━━━━━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━┼━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┨
┃   UART6_RX    ┃   PC7     ┃  PG9      ┃           ┃   Channel5/DMA2_Steam2                ┃  LL_GPIO_AF8   ┃
┃   UART6_TX    ┃   PC6     ┃  PG14     ┃           ┃   Channel5/DMA2_Steam6/DMA2_Steam7    ┃                ┃
┗━━━━━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┛
************************************************************************************************************/
UART_Config g_uartConfig[UART_MAX]={0};
extern Pin_ST g_pinsGroup[STM32_GPIO_GROUP_MAX * STM32_GPIO_PIN_MAX];

//uint32_t UARTx[UART_MAX]={(uint32_t)USART1, (uint32_t)USART2, (uint32_t)USART3, (uint32_t)UART4, (uint32_t)UART5, (uint32_t)USART6};
// 中断号
static uint8_t UART_IRQn[UART_MAX] = {USART1_IRQn, USART2_IRQn, USART3_IRQn, UART4_IRQn, UART5_IRQn, USART6_IRQn};
// 接收缓冲区长度
static uint16_t UART_RX_LEN[UART_MAX] = {UART1_RX_LEN, UART2_RX_LEN, UART3_RX_LEN, UART4_RX_LEN, UART5_RX_LEN, UART6_RX_LEN};
// 引脚配置
static uint16_t g_uartPinMap[UART_MAX][2] = {
    {UART1_RX, UART1_TX},
    {UART2_RX, UART2_TX},
    {UART3_RX, UART3_TX},
    {UART4_RX, UART4_TX},
    {UART5_RX, UART5_TX},
    {UART6_RX, UART6_TX},
};
// dma中断号
static uint8_t g_uartDmaIRQn[UART_MAX][2] = {
    {DMA2_Stream2_IRQn, DMA2_Stream7_IRQn},
    {DMA1_Stream5_IRQn, DMA1_Stream6_IRQn},
    {DMA1_Stream1_IRQn, DMA1_Stream3_IRQn},
    {DMA1_Stream2_IRQn, DMA1_Stream4_IRQn},
    {DMA1_Stream0_IRQn, DMA1_Stream7_IRQn},
    {DMA2_Stream2_IRQn, DMA2_Stream6_IRQn},
};
// dma流
static uint32_t g_uartDmaStream[UART_MAX][2] = {
    {LL_DMA_STREAM_2, LL_DMA_STREAM_7},
    {LL_DMA_STREAM_5, LL_DMA_STREAM_6},
    {LL_DMA_STREAM_1, LL_DMA_STREAM_3},
    {LL_DMA_STREAM_2, LL_DMA_STREAM_4},
    {LL_DMA_STREAM_0, LL_DMA_STREAM_7},
    {LL_DMA_STREAM_2, LL_DMA_STREAM_6},
};
// 阻塞状态
static uint32_t g_uartBlockState[UART_MAX][2] = {
    {0, 0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}
};
static uint8_t g_uartRxBuffer_1[UART1_RX_LEN];
static uint8_t g_uartRxBuffer_2[UART2_RX_LEN];
static uint8_t g_uartRxBuffer_3[UART3_RX_LEN];
static uint8_t g_uartRxBuffer_4[UART4_RX_LEN];
static uint8_t g_uartRxBuffer_5[UART5_RX_LEN];
static uint8_t g_uartRxBuffer_6[UART6_RX_LEN];
// dma中断向量
static DMA_PROC_FUNC g_RxDmaHandler[UART_MAX]={
	UART1_RxDmaHandler,
	UART2_RxDmaHandler,
	UART3_RxDmaHandler,
	UART4_RxDmaHandler,
	UART5_RxDmaHandler,
	UART6_RxDmaHandler
};
// 串口中断向量
static HWI_PROC_FUNC g_RecvHandler[UART_MAX] = {
	UART1_RecvHandler,
	UART2_RecvHandler,
	UART3_RecvHandler,
	UART4_RecvHandler,
	UART5_RecvHandler,
	UART6_RecvHandler
};

static void UART1_RecvHandler(HWI_ARG_T arg)
{
    printf("---interrupt handler---\n");
    // 空闲中断
    if (LL_USART_IsActiveFlag_IDLE(g_uartConfig[0].UARTx)){
        // 关闭DMA
        LL_DMA_DisableStream(g_uartConfig[0].dma, g_uartConfig[0].rxStream);
        // 清空空闲标记
        LL_USART_ClearFlag_IDLE(g_uartConfig[0].UARTx);
        // 获取数据长度
        uint16_t len = UART1_RX_LEN - LL_DMA_GetDataLength(g_uartConfig[0].dma, g_uartConfig[0].rxStream);
        // 入队
        for(uint16_t i=0; i<len; i++)
            QueueIn(g_uartConfig[0].recvID, &g_uartRxBuffer_1[i]);
        // 重新设置计数
        LL_DMA_SetDataLength(g_uartConfig[0].dma, g_uartConfig[0].rxStream, UART1_RX_LEN);
        // 打开DMA
        LL_DMA_EnableStream(g_uartConfig[0].dma, g_uartConfig[0].rxStream);
    }
}
static void UART1_RxDmaHandler()
{
    // 检查DMA传输完成中断
    if (LL_DMA_IsActiveFlag_TC2(DMA2)){
        LL_DMA_ClearFlag_TC2(DMA2);
        // 处理传输完成事件（可选）
    } 
    // 检查DMA传输错误中断
    if (LL_DMA_IsActiveFlag_TE2(DMA2)){
        LL_DMA_ClearFlag_TE2(DMA2);
        // 处理传输错误事件
    }
}


static void UART2_RecvHandler(HWI_ARG_T arg)
{
    // printf("---interrupt handler---\n");
    // 空闲中断
    if (LL_USART_IsActiveFlag_IDLE(g_uartConfig[1].UARTx)){
        LL_DMA_DisableStream(g_uartConfig[1].dma, g_uartConfig[1].rxStream);
        LL_USART_ClearFlag_IDLE(g_uartConfig[1].UARTx);
        uint16_t len = UART2_RX_LEN - LL_DMA_GetDataLength(g_uartConfig[1].dma, g_uartConfig[1].rxStream);
        for(uint16_t i=0; i<20; i++)
            QueueIn(g_uartConfig[1].recvID, &g_uartRxBuffer_2[i]);
        LL_DMA_SetDataLength(g_uartConfig[1].dma, g_uartConfig[1].rxStream, UART2_RX_LEN);
        LL_DMA_EnableStream(g_uartConfig[1].dma, g_uartConfig[1].rxStream);
    }
}
static void UART2_RxDmaHandler()
{
    // 检查DMA传输完成中断
    if (LL_DMA_IsActiveFlag_TC5(DMA1)){
        LL_DMA_ClearFlag_TC5(DMA1);
        // 处理传输完成事件（可选）
    }
 
    // 检查DMA传输错误中断
    if (LL_DMA_IsActiveFlag_TE5(DMA1)){
        LL_DMA_ClearFlag_TE5(DMA1);
        // 处理传输错误事件
    }    
}



static void UART3_RecvHandler(HWI_ARG_T arg)
{
    printf("---interrupt handler---\n");
}
static void UART3_RxDmaHandler()
{
    
}


static void UART4_RecvHandler(HWI_ARG_T arg)
{
    printf("---interrupt handler---\n");
}
static void UART4_RxDmaHandler()
{
    
}


static void UART5_RecvHandler(HWI_ARG_T arg)
{
    printf("---interrupt handler---\n");
}
static void UART5_RxDmaHandler()
{
    
}


static void UART6_RecvHandler(HWI_ARG_T arg)
{
    printf("---interrupt handler---\n");
}
static void UART6_RxDmaHandler()
{
    
}



USART_TypeDef *LL_GET_USARTx(uint8_t id)
{
    switch(id)
    {
        case 1: return USART1;
        case 2: return USART2;
        case 3: return USART3;
        case 4: return UART4;
        case 5: return UART5;
        case 6: return USART6;
    }
}

uint8_t LL_UART_CONFIG_Init(uint8_t id)
{
    // 阻塞状态
    g_uartConfig[id - 1].rxBlock = g_uartBlockState[id-1][0];
    g_uartConfig[id - 1].txBlock = g_uartBlockState[id-1][1];
    // 串口号
    g_uartConfig[id - 1].UARTx = LL_GET_USARTx(id);
	// 中断号
    g_uartConfig[id - 1].UART_IRQn = UART_IRQn[id - 1];
	// 接收队列id
    g_uartConfig[id - 1].recvID = 0xff;
	// 接收缓冲区大小
    g_uartConfig[id - 1].recvLen = UART_RX_LEN[id - 1];
    // 获取引脚
    g_uartConfig[id - 1].rxPin = g_uartPinMap[id - 1][0];
    g_uartConfig[id - 1].txPin = g_uartPinMap[id - 1][1];
    // 设置引脚复用
    if (id < 3){
        LL_CONFIG_GPIO(g_uartConfig[id - 1].rxPin, LL_GPIO_MODE_ALTERNATE, LL_GPIO_PULL_NO, LL_GPIO_SPEED_FREQ_VERY_HIGH, LL_GPIO_OUTPUT_PUSHPULL, LL_GPIO_AF_7);
        LL_CONFIG_GPIO(g_uartConfig[id - 1].txPin, LL_GPIO_MODE_ALTERNATE, LL_GPIO_PULL_NO, LL_GPIO_SPEED_FREQ_VERY_HIGH, LL_GPIO_OUTPUT_PUSHPULL, LL_GPIO_AF_7);
    }
    else{
        LL_CONFIG_GPIO(g_uartConfig[id - 1].rxPin, LL_GPIO_MODE_ALTERNATE, LL_GPIO_PULL_NO, LL_GPIO_SPEED_FREQ_VERY_HIGH, LL_GPIO_OUTPUT_PUSHPULL, LL_GPIO_AF_8);
        LL_CONFIG_GPIO(g_uartConfig[id - 1].txPin, LL_GPIO_MODE_ALTERNATE, LL_GPIO_PULL_NO, LL_GPIO_SPEED_FREQ_VERY_HIGH, LL_GPIO_OUTPUT_PUSHPULL, LL_GPIO_AF_8);
    }
	g_uartConfig[id-1].recvHandler = g_RecvHandler[id-1];
    // // 初始化GPIO
    /************************* 初始化 RX引脚 ******************************/
    STM32_GPIO_GROUP group = (g_uartConfig[id - 1].rxPin) / 16;
    // 打开时钟
    LL_AHB1_GRP1_EnableClock(LL_GET_GPIO_CLK(group));
    GPIO_TypeDef *GPIOx = LL_GET_GPIOX((group));
    // 初始化引脚
    if (LL_GPIO_Init(GPIOx, &g_pinsGroup[g_uartConfig[id - 1].rxPin].gpioInitStruct) != SUCCESS)
    {
        printf("%s line %d error : LL_GPIO_Init Uart%d rx pin failed...\n", __func__, __LINE__, id + 1);
        return ERROR;
    }
    /************************* 初始化 TX引脚 ******************************/
    // 改变引脚编号，其余参数一样
    group = (g_uartConfig[id - 1].txPin) / 16;
    // 打开时钟
    LL_AHB1_GRP1_EnableClock(LL_GET_GPIO_CLK(group));
    GPIOx = LL_GET_GPIOX((group));
    // 初始化引脚
    if (LL_GPIO_Init(GPIOx, &g_pinsGroup[g_uartConfig[id - 1].txPin].gpioInitStruct) != SUCCESS)
    {
        printf("%s line %d error : LL_GPIO_Init Uart%d tx pin failed...\n", __func__, __LINE__, id + 1);
        return ERROR;
    }
    return SUCCESS;
}

void LL_UART_DMA_Init(uint8_t id)
{
	uint8_t *g_uartBuffer[UART_MAX] = {
		g_uartRxBuffer_1, g_uartRxBuffer_2,
		g_uartRxBuffer_3, g_uartRxBuffer_4,
		g_uartRxBuffer_5, g_uartRxBuffer_6
	};
	// dma
	if(id==1 || id==6)
        g_uartConfig[id - 1].dma = DMA2;
    else
        g_uartConfig[id - 1].dma = DMA1;
	// 通道
    if(id==6)
        g_uartConfig[id - 1].dmaChannel = LL_DMA_CHANNEL_5;
    else
        g_uartConfig[id - 1].dmaChannel = LL_DMA_CHANNEL_4;
	// 流
    g_uartConfig[id - 1].rxStream = g_uartDmaStream[id - 1][0];
	// 中断号
    g_uartConfig[id - 1].rxDmaIRQn = g_uartDmaIRQn[id - 1][0];
	// 打开时钟
	if(id==1||id==6)
		LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2);
	else
		LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
    // DMA中断处理函数
	g_uartConfig[id - 1].rxDmaHandler = g_RxDmaHandler[id-1];
    // 配置DMA地址参数
	LL_DMA_ConfigAddresses(g_uartConfig[id - 1].dma, g_uartConfig[id - 1].rxStream, (uint32_t)LL_USART_DMA_GetRegAddr(g_uartConfig[id - 1].UARTx), g_uartBuffer[id-1], LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
    // DMA通道选择
    LL_DMA_SetChannelSelection(g_uartConfig[id - 1].dma, g_uartConfig[id - 1].rxStream, g_uartConfig[id - 1].dmaChannel);
    // DMA传输方向
    LL_DMA_SetDataTransferDirection(g_uartConfig[id - 1].dma, g_uartConfig[id - 1].rxStream, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
    LL_DMA_SetDataLength(g_uartConfig[id - 1].dma, g_uartConfig[id-1].rxStream, g_uartConfig[id-1].recvLen);
    // DMA传输级别
    LL_DMA_SetStreamPriorityLevel(g_uartConfig[id - 1].dma, g_uartConfig[id - 1].rxStream, LL_DMA_PRIORITY_VERYHIGH);
    // DMA循环模式
    LL_DMA_SetMode(g_uartConfig[id - 1].dma, g_uartConfig[id - 1].rxStream, LL_DMA_MODE_CIRCULAR);
    // DMA地址增长方式
    LL_DMA_SetPeriphIncMode(g_uartConfig[id - 1].dma, g_uartConfig[id - 1].rxStream, LL_DMA_PERIPH_NOINCREMENT);
    LL_DMA_SetMemoryIncMode(g_uartConfig[id - 1].dma, g_uartConfig[id - 1].rxStream, LL_DMA_MEMORY_INCREMENT);
    // DMA增长长度
    LL_DMA_SetPeriphSize(g_uartConfig[id - 1].dma, g_uartConfig[id - 1].rxStream, LL_DMA_PDATAALIGN_BYTE);
    LL_DMA_SetMemorySize(g_uartConfig[id - 1].dma, g_uartConfig[id - 1].rxStream, LL_DMA_MDATAALIGN_BYTE);
    // 禁用DMA FIFO
    LL_DMA_DisableFifoMode(g_uartConfig[id - 1].dma, g_uartConfig[id - 1].rxStream);    
    // 配置DMA中断
    NVIC_SetVector(g_uartConfig[id - 1].rxDmaIRQn, (uint32_t)g_uartConfig[id - 1].rxDmaHandler);
    NVIC_SetPriority(g_uartConfig[id - 1].rxDmaIRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
    NVIC_EnableIRQ(g_uartConfig[id - 1].rxDmaIRQn);
}

void LL_UART_DMA_DeInit(uint8_t id)
{
	// 禁止DMA
    LL_DMA_DisableStream(g_uartConfig[id-1].dma, g_uartConfig[id-1].rxStream);
	// 禁止DMA中断
    NVIC_DisableIRQ(g_uartConfig[id - 1].rxDmaIRQn);
    // 禁止DMA发送
    LL_DMA_DisableIT_TC(g_uartConfig[id - 1].dma, g_uartConfig[id - 1].rxStream);
    LL_DMA_DisableIT_TE(g_uartConfig[id - 1].dma, g_uartConfig[id - 1].rxStream);
}